////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2001-2004.
// -------------------------------------------------------------------------
//  File name:   PrefabObject.h
//  Version:     v1.00
//  Created:     13/11/2003 by Timur.
//  Compilers:   Visual Studio.NET 2003
//  Description: 
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////

#ifndef __PrefabBuildingObject_h__
#define __PrefabBuildingObject_h__
#pragma once

#include "PrefabObject.h"
#include "Prefabs\PrefabItem.h"

class CPrefabItem;

#define PREFABBUILDING_OBJECT_CLASS_NAME "PrefabBuilding"

/*!
*		CPrefabBuildingObject is prefabricated object which can contain multiple other objects, in a group like manner, 
		but internal objects can not be modified, they are only created from PrefabItem.
*/
class CPrefabBuildingObject : public CPrefabObject
{
public:
	DECLARE_DYNCREATE(CPrefabBuildingObject)

	//////////////////////////////////////////////////////////////////////////
	// CPrefabBuildingObject overrides. 
	//////////////////////////////////////////////////////////////////////////
	bool Init( IEditor *ie,CBaseObject *prev,const CString &file );
	void Done();

	void Display( DisplayContext &disp );
	bool HitTest( HitContext &hc );

	void BeginEditParams( IEditor *ie,int flags );
	void EndEditParams( IEditor *ie );

	virtual void EnableEditParams(bool bEnable);
	virtual void EnableEditMultiSelParams(bool bEnable, bool bAllOfSameType);

	void OnEvent( ObjectEvent event );

	void Serialize( CObjectArchive &ar );
	void SetMaterialLayersMask( uint32 nLayersMask );

	//! Attach new child node.
	virtual void AttachChild( CBaseObject* child,bool bKeepPos=true );
	
protected:
	virtual void RemoveChild( CBaseObject *child );

public:
	virtual XmlNodeRef Export( const CString &levelPath,XmlNodeRef &xmlNode );

public:
	//////////////////////////////////////////////////////////////////////////
	// CPrefabBuildingObject.
	//////////////////////////////////////////////////////////////////////////
	virtual void SetPrefab( REFGUID guid,bool bForceReload );
	virtual void SetPrefab( CPrefabItem *pPrefab,bool bForceReload );
	CPrefabItem* GetPrefab() const;

	// Extract all objects inside.
	void ExtractAll();
	void ExtractObject( CBaseObject *pObj );
	void AddObjectToPrefab( CBaseObject *pObj, bool isMultyAdding=false );
	void RemoveObjectFromPrefab( CBaseObject *pObj );
	void UpdatePrefab();

	//////////////////////////////////////////////////////////////////////////
	// Procedural Floor Management.
	//////////////////////////////////////////////////////////////////////////
	float GetFloorHeight(int floorNumber){ if (GetPrefab()) return GetPrefab()->GetFloorHeight(floorNumber); else return 0.0; };
	void SetFloorHeight(float floorHeight, int floorNumber) { if (GetPrefab()) GetPrefab()->SetFloorHeight(floorHeight,floorNumber); };
	int GetFloorCount()	{ if (GetPrefab()) return GetPrefab()->GetFloorCount(); else return 0;};
	void DeleteFloor(int floorNumber) { if (floorNumber>0 && GetPrefab()) GetPrefab()->DeleteFloor(floorNumber);};

	void SetFloorHeightUserDefined(int floorNumber, bool floorHasUserDefinedHeight){ if ( GetPrefab() ) GetPrefab()->SetFloorHeightUserDefined(floorNumber, floorHasUserDefinedHeight); };
	bool IsFloorHeightDefinedByUser(int floorNumber) { if (GetPrefab()) return GetPrefab()->IsFloorHeightDefinedByUser( floorNumber ); else return false; };

	bool IsBuildingModified() { return m_buildingObjectsModified; };
	void SetBuildingModified( bool buildingObjectsModified ) { m_buildingObjectsModified=buildingObjectsModified; };

protected:
	CPrefabBuildingObject();

	virtual void PostClone( CBaseObject *pFromObject,CObjectCloneContext &ctx );
	virtual void CalcBoundBox();
	void DeleteThis() { delete this; };
	
	void RecursivelySetObjectInPrefab( CBaseObject *object );
	void RecursivelyDisplayObject( CBaseObject *object,DisplayContext &dc );
	void DeleteAllPrefabObjects();
	void InvalidateBBox() { m_bBBoxValid = false; };

protected:
	_smart_ptr<CPrefabItem> m_pPrefabItem;

	CString m_prefabName;
	GUID m_prefabGUID;
	bool m_buildingObjectsModified;
};

/*!
* Class Description of CPrefabBuildingObject.
*/
class CPrefabBuildingObjectClassDesc : public CObjectClassDesc
{
public:
	REFGUID ClassID()
	{
		// {931962ED-450F-443e-BFA4-1BBDAA061202}
		static const GUID guid = 
		{ 0x931962ed, 0x450f, 0x443e, { 0xbf, 0xa4, 0x1b, 0xbd, 0xaa, 0x6, 0x12, 0x2 } };
		return guid;
	}
	ObjectType GetObjectType() { return OBJTYPE_PREFAB; };
	const char* ClassName() { return PREFABBUILDING_OBJECT_CLASS_NAME; };
	const char* Category() { return "Prefabs"; };
	CRuntimeClass* GetRuntimeClass() { return RUNTIME_CLASS(CPrefabBuildingObject); };

	//! Select all prefabs.
	//! ObjectTreeBrowser object can recognize this hardcoded name.
	const char* GetFileSpec() { return "*Prefabs"; };
	virtual const char* GetTextureIcon() { return "Editor/ObjectIcons/prefabbuilding.bmp"; };
	int GameCreationOrder() { return 210; };
};

#endif // __PrefabBuildingObject_h__